/*
   This file is part of the 'Let's Do Stuff Together' project
   http://code.google.com/p/dostufftogether/

   Copyright 2010 Christoph Fuchs, Stefan Thaler

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package search;

import static activity.ActivityParameters.ALTITUDE;
import static activity.ActivityParameters.CATEGORY;
import static activity.ActivityParameters.DESCRIPTION;
import static activity.ActivityParameters.END_TIME;
import static activity.ActivityParameters.LATITUDE;
import static activity.ActivityParameters.LONGITUDE;
import static activity.ActivityParameters.RANGE;
import static activity.ActivityParameters.START_TIME;
import static activity.ActivityParameters.TITLE;

import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import location.ECEFCoordinates;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import persistence.ActivityEntity;
import activity.Activity;

import com.google.gson.Gson;

/**
 * Search within distance.
 * 
 * @author Stefan
 * 
 */
public class SearchActivitesServlet extends HttpServlet {
	private static final Log log = LogFactory
			.getLog(SearchActivitesServlet.class);

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		Set<String> categories = null;
		Long startTime = null, endTime = null;
		Integer range = null;
		Double longitude = null, latitude = null, altitude = null;
		String activityTitle = null, activityDescription = null;

		// parse parameters
		if (req.getParameter(RANGE) != null) {
			range = Integer.parseInt(req.getParameter(RANGE));
		}
		if (req.getParameter(START_TIME) != null) {
			startTime = Long.parseLong(req.getParameter(START_TIME));
		}
		if (req.getParameter(END_TIME) != null) {
			endTime = Long.parseLong(req.getParameter(END_TIME));
		}
		if (req.getParameter(CATEGORY) != null) {
			StringTokenizer st = new StringTokenizer(
					req.getParameter(CATEGORY), ",");
			categories = new HashSet<String>();
			while (st.hasMoreTokens()) {
				categories.add(st.nextToken());
			}
		}
		if (req.getParameter(LATITUDE) != null) {
			latitude = Double.parseDouble(req.getParameter(LATITUDE));
		}
		if (req.getParameter(LONGITUDE) != null) {
			longitude = Double.parseDouble(req.getParameter(LONGITUDE));
		}
		if (req.getParameter(ALTITUDE) != null) {
			altitude = Double.parseDouble(req.getParameter(ALTITUDE));
		}
		//
		if (req.getParameter(DESCRIPTION) != null) {
			activityDescription = req.getParameter(DESCRIPTION);
		}
		if (req.getParameter(TITLE) != null) {
			activityTitle = req.getParameter(TITLE);
		}

		Activity[] searchResult = null;
		// get instances
		if (req.getParameter("doFakeSearch") != null) {
			searchResult = doFakeSearch();
			log.trace("faking search");
		} else {
			Set<Activity> activities = ActivityEntity.getInstances(latitude,
					longitude, altitude, range, startTime, endTime, categories,
					activityTitle, activityDescription);

			// hack because gson writer doesnt accept .toArray &
			// toArray(Activity[]) because of the sesame proxy manager field which has a circualr reference 
			// and is not transient
			searchResult = new Activity[activities.size()];
			Iterator<Activity> activityIterator = activities.iterator();
			for (int i = 0; i < activities.size(); i++) {
				searchResult[i] = ((ActivityEntity) activityIterator.next()).getInstanceCopy();
			}
		}

		Gson gson = new Gson();
		try {
			resp.getWriter().write(
					gson.toJson(searchResult, ActivityEntity[].class)
							.toString());
		} catch (Exception e) {
			log.error("Failed to convert searchresults to JSON due to "
					+ e.getMessage());
			resp.getWriter().write(
					gson.toJson(new Activity[0], ActivityEntity[].class)
							.toString());
		}

	}

	public static Activity[] doFakeSearch() {
		Random r = new Random(System.currentTimeMillis());
		Activity[] activities = new Activity[Math.abs(r.nextInt() % 5 + 1)];

		int i = 0;
		byte[] bytes = new byte[20];
		byte[] descriptionBytes = new byte[100];
		ECEFCoordinates activityLocation;
		for (i = 0; i < activities.length; i++) {
			Activity activity = new ActivityEntity();

			activity.setId("ACY" + System.currentTimeMillis());
			r.nextBytes(bytes);
			activity.setTitle("RANDOM TITLE " + new String(bytes));
			r.nextBytes(descriptionBytes);
			activity.setDescription("RANDOM DESCRIPTION "
					+ new String(descriptionBytes));

			activity.setStartTime(System.currentTimeMillis() + 3600);
			activity.setEndTime(System.currentTimeMillis() + 7200);

			activityLocation = new ECEFCoordinates(r.nextDouble()
					* (r.nextInt() % 90), r.nextDouble() * (r.nextInt() % 90),
					r.nextDouble() * (r.nextInt() % 1000));

			activity.setX(activityLocation.getX());
			activity.setY(activityLocation.getY());
			activity.setZ(activityLocation.getZ());

			activity.setLongitude(activityLocation.getX());
			activity.setLatitude(activityLocation.getY());
			activity.setAltitude(activityLocation.getZ());

			activities[i] = activity;
		}

		return activities;
	}
}
